package com.example.app_emu.core

import android.util.Log
import com.example.app_emu.core.control.DebugRPC
import com.example.app_emu.core.control.IRPCSupport
import com.example.lib_core.util.JsonUtils
import com.example.session.EndPoint
import com.example.session.IEndPoint
import java.net.UnknownHostException
import java.util.LinkedHashMap

class Emulator: IEmulatorContext, IEmulatorSession, IRPCSupport {

    private val deviceHash: LinkedHashMap<String, EmulatorDevice> = LinkedHashMap()
    private var debugLink: EmulatorDebugLink = EmulatorDebugLink(EmulatorDebugLink.Option())

    fun isRunning(): Boolean {
        return debugLink.isOpened
    }

    fun getDevice(): List<EmulatorDevice>{
        return deviceHash.map { it.value }
    }

    @Throws(UnknownHostException::class, LinkException::class)
    fun start(option: EmulatorDebugLink.Option) {
        stop()

        debugLink = EmulatorDebugLink(option)
        debugLink.setOnLinkListener(object : OnLinkListener {
            override fun onReceived(payload: ByteArray) {
                onReceiveRPC(String(payload))
            }

            override fun onError(message: String, e: Exception) {
                System.err.println(message + " " + e.message)
            }

            override fun onLog(message: String) {
                System.err.println(message)
            }
        })
        debugLink.open()
    }

    override fun onReceiveRPC(json: String) {
        val rpc = JsonUtils.gson.fromJson(json, DebugRPC::class.java)
        try {
            val key = rpc.target
            val device = deviceHash[key]
            device?.onRPC(rpc)
            if (rpc.method == "get_ip"){
                deviceHash.values.forEach {
                    val rpc = DebugRPC()
                    rpc.method ="get_ip"
                    rpc.params["ip"] = it.profile.ip.toString()
                    it.responseRPC(rpc)
                }
            }

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun stop() {
        debugLink.close()
    }

    override fun sendTo(buffer: ByteArray) {
        debugLink.sendTo(buffer)
    }

    fun registerDevice(device: EmulatorDevice) {
        deviceHash.put(device.profile.sn, device)
    }

    override fun getSession(): IEmulatorSession {
        return this
    }
}